import { isPlainObject } from "lodash";
import { deepMerge } from "../helpers/util";
import { AxiosRequestConfig } from "../types";

const strats = Object.create(null);

function defaultStrat(val1: any, val2: any): any {
  return typeof val2 !== 'undefined' ? val2 : val1
}

function fromVal2Strat(val1: any, val2: any): any {
  if (typeof val2 !== 'undefined') {
    return val2
  }
}

function deepMergeStrat (val1: any, val2: any): any {
  if (isPlainObject(val2)) {
    return deepMerge(val1, val2);
  } else if (!val2) {
    return val2;
  } else if (isPlainObject(val1)) {
    return deepMerge(val1);
  } else {
    return val1;
  }
}

const stratKeysFromVal2 = ['url', 'params', 'data'];

stratKeysFromVal2.forEach(key => {
  strats[key] = fromVal2Strat
})

const stratKeysDeepMerge = ['headers', 'auth']

stratKeysDeepMerge.forEach(key => {
  strats[key] = deepMergeStrat;
})

export default function mergeConfig(
  config1: AxiosRequestConfig,
  config2?: AxiosRequestConfig
): AxiosRequestConfig {
  if (!config2) {
    return config1;
  }

  type configType = keyof AxiosRequestConfig;

  const config = Object.create(null);

  for (let key in config2) {
    mergeField(key as configType);
  }

  for (let key in config1) {
    if (!config2[key as configType]) {
      mergeField(key as configType);
    }
  }

  function mergeField (key: configType):void {
    const strat = strats[key] || defaultStrat;
    config[key] = strat(config1[key], config2![key]);
  }
  return config;
}